/*
 * Copyright (c) 2025 EasyAdmin
 * All rights reserved.
 *
 * This file is part of the [EasAdmin] project.
 * Unauthorized copying of this file, via any medium, is strictly prohibited.
 * Proprietary and confidential.
 *
 * Author: EasyAdmin ( 1073602@qq.com )
 * Website: https://www.xhxiao.com
 */
package com.easy.module.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.framework.common.exception.ServiceException;
import com.easy.framework.common.utils.Func;
import com.easy.framework.common.utils.SpringUtils;
import com.easy.framework.security.annotation.DataScope;
import com.easy.framework.security.model.Role;
import com.easy.framework.security.utils.SecurityUtils;
import com.easy.module.system.entity.SysRole;
import com.easy.module.system.entity.SysRoleDept;
import com.easy.module.system.entity.SysRoleMenu;
import com.easy.module.system.mapper.SysRoleDeptMapper;
import com.easy.module.system.mapper.SysRoleMapper;
import com.easy.module.system.mapper.SysRoleMenuMapper;
import com.easy.module.system.mapper.SysUserRoleMapper;
import com.easy.module.system.query.SysRoleQuery;
import com.easy.module.system.service.ISysRoleService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 角色管理 Service业务
 *
 * @author EasyAdmin ( 1073602@qq.com )
 * @date 2025-08-19
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Resource
    private SysRoleMenuMapper roleMenuMapper;

    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private SysRoleDeptMapper roleDeptMapper;

    /**
     * 获取查询对象
     *
     * @param query
     * @return
     */
    @Override
    public LambdaQueryWrapper<SysRole> lambdaQuery(SysRoleQuery query) {
        Optional<LambdaQueryWrapper<SysRole>> optional = lambdaQueryOptional(query);
        optional.ifPresent(w -> w.apply(Func.isNotEmpty(query.getDataScope()), query.getDataScope()));
        return optional.orElse(null);
    }

    /**
     * 查询角色信息列表
     *
     * @param query 角色信息
     * @return 角色信息
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<SysRole> queryList(SysRoleQuery query) {
        return list(lambdaQuery(query));
    }

    /**
     * 新增角色信息
     *
     * @param dto 角色信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(SysRole dto) {
        save(dto);
        return insertRoleMenu(dto) > 0;
    }

    /**
     * 修改角色信息
     *
     * @param dto 角色信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(SysRole dto) {
        // 修改角色信息
        updateById(dto);
        // 删除角色与菜单关联
        roleMenuMapper.deleteByRoleId(dto.getId());
        return insertRoleMenu(dto) > 0;
    }

    /**
     * 批量删除角色信息
     *
     * @param roleIds 需要删除的角色信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(Long[] roleIds) {
        for (Long roleId : roleIds) {
            validateDataScope(roleId);
            SysRole role = getById(roleId);
            if (userRoleMapper.countByRoleId(roleId) > 0) {
                throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }
//        // 删除角色与菜单关联
//        roleMenuMapper.delete(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId, roleIds));
//        // 删除角色与部门关联
//        roleDeptMapper.delete(Wrappers.<SysRoleDept>lambdaQuery().eq(SysRoleDept::getRoleId, roleIds));
        return removeBatchByIds(List.of(roleIds));
    }

    /**
     * 校验角色是否有数据权限
     *
     * @param roleId 角色id
     */
    @Override
    public void validateDataScope(Long roleId) {
        if (!SecurityUtils.isAdmin()) {
            SysRoleQuery query = new SysRoleQuery();
            query.setId(roleId);
            List<SysRole> roles = SpringUtils.getAopProxy(this).list(query);
            if (Func.isEmpty(roles)) {
                throw new ServiceException("没有权限访问角色数据！");
            }
        }
    }


    /**
     * 新增角色菜单信息
     *
     * @param role 角色对象
     */
    public int insertRoleMenu(SysRole role) {
        int rows = 1;
        // 新增用户与角色管理
        List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
        for (Long menuId : role.getMenuIds()) {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setRoleId(role.getId());
            rm.setMenuId(menuId);
            list.add(rm);
        }
        if (list.size() > 0) {
            rows = roleMenuMapper.addBatch(list);
        }
        return rows;
    }

    @Override
    public List<Long> getRoleIdListByUserId(Long userId) {
        List<Long> roleIdList=new ArrayList<>();
        if (Func.isNotEmpty(userId)) {
            roleIdList = userRoleMapper.getRoleIdListByUserId(userId);
        }
        return roleIdList;
    }

    @Override
    public List<SysRole> getRoleListByUserId(Long userId) {
        List<SysRole> roleList = new ArrayList<>();
        if (Func.isNotEmpty(userId)) {
            List<Long> roleIdList = getRoleIdListByUserId(userId);
            if (Func.isNotEmpty(roleIdList)) {
                roleList = list(Wrappers.<SysRole>lambdaQuery().in(SysRole::getId, roleIdList));
            }
        }
        return roleList;
    }

    @Override
    public List<Role> getRolesByUserId(Long userId) {
        List<Role> roleList = new ArrayList<>();
        List<SysRole> roles = getRoleListByUserId(userId);
        if (Func.isNotEmpty(roles)) {
            roles.forEach(role -> {
                List<Long> deptIds = roleDeptMapper.getDeptIdListByRoleId(role.getId());
                roleList.add(new Role(role.getId(), role.getRoleKey(), role.getDataScope(), deptIds));
            });
        }
        return roleList;
    }

    @Override
    public List<Long> getDeptIdListByRoleId(Long roleId) {
        return roleDeptMapper.getDeptIdListByRoleId(roleId);
    }

    /**
     * 修改数据权限信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Transactional
    @Override
    public Boolean authDataScope(SysRole role) {
        // 修改角色信息
        updateById(role);
        // 删除角色与部门关联
        roleDeptMapper.deleteByRoleId(role.getId());
        if(Func.isNotEmpty(role.getDeptIds())){
            // 新增角色与部门（数据权限）管理
            List<SysRoleDept> list = new ArrayList<SysRoleDept>();
            for (Long deptId : role.getDeptIds()) {
                SysRoleDept rd = new SysRoleDept();
                rd.setRoleId(role.getId());
                rd.setDeptId(deptId);
                list.add(rd);
            }
            roleDeptMapper.insert(list);
        }
        return true;
    }
}
